#include "flatui.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "websocketclientwrapper.h"

#include <QWebSocketServer>
#include <QTimer>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    bool flag =true;
    wsServer = new QWebSocketServer (QStringLiteral("QWebChannel Standalone Example Server"), QWebSocketServer::NonSecureMode);
    if (!wsServer->listen(QHostAddress::LocalHost, 12345)) {
        AppendLog(QString("listen local port 12345 failed, %1").arg(wsServer->errorString()));
        flag = false;
    }
    connect(wsServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
    ClientChange();
    mCurrentWeb = nullptr;
    if( flag )
        AppendLog( QString("ws open success, bind port 12345") );
    //    connect(&pingTmr,SIGNAL(timeout()),this,SLOT(onPingTimeout));
    //    pingTmr.start(1000);
    //   FlatUI::SetAllFlatUI(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::AppendLog(QString t)
{
    QString m= QDateTime::currentDateTime().toString("[HH:MM:SS.ZZZ]");
    ui->plainTextEdit->appendPlainText(  m + t );
}

void MainWindow::ViewSendText(QString t)
{
    QString m= QDateTime::currentDateTime().toString("[HH:MM:SS.ZZZ]");
    ui->plainTextEdit->appendPlainText( m + t );
}

void MainWindow::ViewRecvText(QString t)
{
    QString m= QDateTime::currentDateTime().toString("[HH:MM:SS.ZZZ]");
    ui->plainTextEdit->appendPlainText( m + t );
}

void MainWindow::ClientChange()
{
    ui->comboBox->clear();
    ui->comboBox->addItem(QString("All(%1)").arg(ClientList.count()));
    foreach (QWebSocket *c, ClientList) {
        QString t = QString("%1:%2").arg( c->peerAddress().toString() ).arg( c->peerPort() );
        ui->comboBox->addItem(t);
    }
}

void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1)
{
    mCurrentWeb = nullptr;
    foreach (QWebSocket *c, ClientList) {
        QString t = QString("%1:%2").arg( c->peerAddress().toString() ).arg( c->peerPort() );
        if(t == arg1 )
        {
            qDebug()<<"Select"<<t<<endl;
            mCurrentWeb = c;
        }
    }
}

void MainWindow::onPingTimeout()
{
    emit PingClient(QByteArray("{\"online\":\"yes\"}"));
}


void MainWindow::RemoveClient()
{
    QWebSocket *c =  (QWebSocket*)sender();
    AppendLog( QString("[%1:%2] disconnected").arg(c->peerAddress().toString()).arg(c->peerPort()));
    if( ClientList.contains(c))
        ClientList.removeOne(c);
    ClientChange();
}

void MainWindow::newConnection()
{
    QWebSocket *c = wsServer->nextPendingConnection();
    AppendLog( QString("[%1:%2] connected").arg(c->peerAddress().toString()).arg(c->peerPort()));
    ClientList.append(c);
    ClientChange();
    connect(c,SIGNAL(disconnected()), this, SLOT(RemoveClient()));
    connect(c,SIGNAL(pong(quint64,QByteArray)),this,SLOT(ClientHasPong(quint64,QByteArray)));
    connect(c,SIGNAL(textFrameReceived(QString,bool)), this, SLOT(textFrameReceived(QString,bool)));
    connect(c,SIGNAL(textMessageReceived(QString)), this, SLOT(textMessageReceived(QString)));
    connect(c,SIGNAL(binaryFrameReceived(QByteArray,bool)), this, SLOT(binaryFrameReceived(QByteArray,bool)));
    connect(c,SIGNAL(binaryMessageReceived(QByteArray)), this, SLOT(binaryMessageReceived(QByteArray)));
    //  connect(this,SIGNAL(PingClient(QByteArray)),c,SLOT(ping(QByteArray)));
}

void MainWindow::textFrameReceived(QString a,bool b)
{
    QWebSocket *c = (QWebSocket*)sender();
    //  AppendLog( QString("[%1][RX] textFrameReceived").arg(c->peerAddress().toString()));
}

void MainWindow::ClientHasPong(quint64 a ,QByteArray b)
{
    QWebSocket *c = (QWebSocket*)sender();
    if( bShowPing )
    {
        AppendLog( QString("[%1][RX] pong").arg(c->peerAddress().toString()));
    }
}

void MainWindow::textMessageReceived(QString a)
{
    QWebSocket *c = (QWebSocket*)sender();
    AppendLog( QString("[%1][TEXT][rx] %2").arg(c->peerAddress().toString()).arg(a));
}

void MainWindow::binaryFrameReceived(QByteArray a,bool b)
{
    QWebSocket *c = (QWebSocket*)sender();
    //  AppendLog( QString("[%1][RX] binaryFrameReceived").arg(c->peerAddress().toString()));
}

void MainWindow::binaryMessageReceived(QByteArray a)
{
    QWebSocket *c = (QWebSocket*)sender();
    AppendLog( QString("[%1][HEX][RX] %2").arg(c->peerAddress().toString()).arg(QString::fromLocal8Bit(a.toHex())));
}

void MainWindow::on_pushButton_snd_clicked()
{
    QString t = ui->lineEdit_input->text();
    if( ClientList.count() == 0 )
    {
        ViewSendText("no client connected..");
        return;
    }
    if( dataMode == DATA_TEXT )
    {
        if(mCurrentWeb==nullptr)
        {
            foreach (QWebSocket *c, ClientList) {
                c->sendTextMessage( t );
                ViewSendText(QString("[%1][TEXT][TX] %2").arg(c->peerAddress().toString()).arg(t));
            }
        }else{
            qDebug()<<"Sendto"<<mCurrentWeb->peerAddress()<<endl;
            mCurrentWeb->sendTextMessage( t );
            ViewSendText(QString("[%1][TEXT][TX] %2").arg(mCurrentWeb->peerAddress().toString()).arg(t));
        }
    }else{
        QByteArray data = QByteArray::fromHex( ui->lineEdit_input->text().toLocal8Bit() );
        if(mCurrentWeb==nullptr)
        {
            foreach (QWebSocket *c, ClientList) {
                c->sendBinaryMessage(data);
                ViewSendText(QString("[%1][HEX][TX]%2").arg(c->peerAddress().toString()).arg(t));
            }
        }else{
            qDebug()<<"Sendto"<<mCurrentWeb->peerAddress()<<endl;
            mCurrentWeb->sendBinaryMessage(data);
            ViewSendText(QString("[%1][HEX][TX] %2").arg(mCurrentWeb->peerAddress().toString()).arg(t));
        }
    }
}


void MainWindow::on_comboBox_type_currentIndexChanged(int index)
{
    if( index == 0 )
        dataMode = DATA_TEXT;
    else
        dataMode = DATA_HEX;
}

void MainWindow::on_pushButton_clicked()
{
    if( wsServer->isListening() )
        wsServer->close();
    wsServer->listen(QHostAddress::Any, ui->lineEdit->text().toInt());
}

void MainWindow::on_pushButton_snd_clear_clicked()
{
    ui->lineEdit_input->text().clear();
}

void MainWindow::on_pushButton_log_clear_clicked()
{
    ui->plainTextEdit->setPlainText("");
}
